package  
{
	import flash.display.Bitmap;
	import flash.display.BitmapData;
	import org.flixel.*;
	import flash.geom.Rectangle;
	import org.flixel.plugin.photonstorm.*;
	/**
	 * ...
	 * @author Kyl
	 */
	public class InkPlatform extends FlxSprite 
	{
		
		public function InkPlatform(X:Number, Y:Number) 
		{
			super(X, Y);
			completed = false;
			dots = new FlxGroup();
			dots.add(new InkPoint(X, Y));
			points = new Array();
			points.push(new FlxPoint(X, Y));
			
			xMax = xMin = X;
			yMax = yMin = Y;
			pixels = new BitmapData(30, 30);
			super.immovable = true;
			playerPresent = true;
		}
		
		// The level will need to add each InkPlatform's group
		// of platforms.  This exposes the group to the level.
		
		// Each platform will be a 1x1 pixel.
		private var points:Array;
		private var dots:FlxGroup;
		private var arc:Bitmap;
		private var arcData:BitmapData;
		private var completed:Boolean;
		
		// Keep track of our bounding box.  We'll update it
		// as new points are added
		private var xMax:Number;
		private var xMin:Number;
		private var yMax:Number;
		private var yMin:Number;
		private const slopeThresh:Number = 0.75;
		
		// Remember if the player was here.  If he was and just left,
		// restore gravity.
		public var playerPresent:Boolean;
		
		override public function draw(): void
		{
			super.draw();
		}
		
		public function isCompleted(): Boolean
		{
			return completed;
		}
		
		public function complete(): void
		{
			completed = true;
		}
		
		public function addPoint(X:Number, Y:Number): void
		{	
			points.push(new FlxPoint(X, Y));
			dots.add(new InkPoint(X,Y));
			if ( X < xMin )
			{
				xMin = X - 26;
				super.x = xMin;
				super.width = (xMax - xMin > 8) ? xMax - super.x + 8: 30;
			}
			if ( X > xMax )
			{
				xMax = X + 4;
				super.width = (X - super.x > 8) ? xMax - super.x + 8 : 30;
			}
			if ( Y < yMin )
			{
				yMin = Y - 26;
				super.y = yMin;
				super.height = (yMax - yMin > 8) ? yMax - super.y + 8 : 30;
			}
			if ( Y > yMax )
			{
				yMax = Y + 4;
				super.height = (Y - super.y > 8) ? yMax - super.y + 8 : 30;
			}
			
			super.pixels = new BitmapData(super.width, super.height, true, 0x00000000);
			super.framePixels = super.pixels;
			
			// Represent each point as a 2x2 to create a nicer-looking arc
			for ( var i:int = 0; i < points.length; i++ )
			{	
				var diffX:Number;
				var diffY:Number;
				
				if ( i == 0 )
				{
					diffX = points[i + 1].x - points[i].x;
					diffY = points[i + 1].y - points[i].y;
				}
				else if ( i == dots.length - 1 )
				{
					diffX = points[i].x - points[i - 1].x;
					diffY = points[i].y - points[i - 1].y;
				}
				else
				{
					diffX = points[i + 1].x - points[i - 1].x;
					diffY = points[i + 1].y - points[i - 1].y;
				}
				
				var pxX:int = points[i].x - super.x;
				var pxY:int = points[i].y - super.y;
				
				if ( diffX == 0 || FlxU.abs(diffY / diffX) > slopeThresh )
				{
					// Make yellow
					var redVal:uint = FlxG.random() * 64;
					redVal += 96;
					//trace(redVal);
					redVal = redVal << 16;
					redVal &= 0x00FF0000;
					redVal |= 0x50000000;
					var yelVal:uint = FlxG.random() * 64;
					yelVal += 164;
					//yelVal = yelVal << 8;
					yelVal &= 0x0000FF00;
					redVal |= yelVal;
					super.pixels.setPixel32(pxX, pxY, redVal);
				}
				else
				{
					// Color black with some minor variation
					var Color:uint = FlxU.abs(diffX * pxX + diffY * pxY) % 64;
					Color = Color << 8;
					Color = Color & 0x0000FF00;
					Color += FlxU.abs(diffX * diffY * points.length) % 64;
					Color = Color << 8;
					Color = Color & 0x00FFFF00;
					Color += FlxU.abs(diffX * pxY + diffY * pxX) % 64;
					Color |= 0x50000000;
					super.pixels.setPixel32(pxX, pxY, Color);
				}
				
				var k:int;
				var j:int;
				var curColor:uint;
				var curAlpha:uint;
				var dist:int;
				
				for ( k = -4; k <= 4; k++ )
				{
					for ( j = -4; j <= 4; j++ )
					{
						curColor = super.pixels.getPixel32(pxX, pxY);
						curColor &= 0x00FFFFFF;
						curAlpha = super.pixels.getPixel32(pxX + k, pxY + j);
						curAlpha = curAlpha >> 24;
						// Left-shift is 1-padded.  Mask out the 1's to get just the 
						// alpha value.
						curAlpha &= 0x000000FF;
						
						dist = FlxU.abs(k) + FlxU.abs(j);
						
						if ( dist <= 2)
							curAlpha += 0x00000040;
						else if ( dist <= 4 )
							curAlpha += 0x00000020;
						else if ( dist <= 5 )
							curAlpha += 0x00000010;
						else if ( dist <= 7 && Math.abs(diffX - k) + Math.abs(diffY - j) < 2 )
							curAlpha += 0x00000004;
						else if ( Math.abs(diffX - k) + Math.abs(diffY - j) < 2 ) 
							curAlpha += 0x00000002;
						
						if ( curAlpha > 0x000000FF ) curAlpha = 0x000000FF;
						
						curAlpha <<= 24;
						curAlpha &= 0xFF000000;
						
						curColor |= curAlpha;
						
						super.pixels.setPixel32(pxX + k, pxY + j, curColor);
					}
				}
			}
				
		}
		
		/* This is where we determine how an object that collides with this
		 * InkPlatform will behave.  For now, just use FlxObject.separate(..)
		 * to perform a basic collision.
		 */
		public function collidePlayer(ply:Player) : void
		{
			var collided:Boolean = false;
			var walkingOn:Boolean = false;
			for ( var i:int = 0; i < dots.length; i++ )
			{
				//if ( FlxCollision.pixelPerfectPointCheck(points[i].x, points[i].y, ply) )
				if ( points[i].x > ply.x && points[i].x < ply.x + ply.frameWidth && 
					 points[i].y > ply.y && points[i].y < ply.y + ply.frameHeight )
				{
					var diffX:Number;
					var diffY:Number;
					
					if ( i == 0 )
					{
						diffX = points[i + 1].x - points[i].x;
						diffY = points[i + 1].y - points[i].y;
					}
					else if ( i == dots.length - 1 )
					{
						diffX = points[i].x - points[i - 1].x;
						diffY = points[i].y - points[i - 1].y;
					}
					else
					{
						diffX = points[i + 1].x - points[i - 1].x;
						diffY = points[i + 1].y - points[i - 1].y;
					}
					
					if ( diffX == 0 || FlxU.abs(diffY / diffX) > slopeThresh || i <= 1 || i >= points.length - 1 )
					{
						FlxObject.separateX(ply, dots.members[i]);
						FlxObject.separateY(ply, dots.members[i]);
					}
					else
					{
						FlxObject.separateY(ply, dots.members[i]);
					}
					
					if (points[i].y > ply.y + ply.frameHeight - 4  && points[i].y < ply.y + ply.frameHeight + 4
						&& points[i].x > ply.x - 1 && points[i].x < ply.x + ply.frameWidth + 1) {
						walkingOn = true;
					}
					
					collided = true;
				}
			}
			
			if (collided && walkingOn)
			{
				playerPresent = true;
				ply.enableInkJump();
				ply.acceleration.y = 1000;
			}
		}
		
		// Call when the ink is done drawing.  It will fill in to show that 
		// it is now collidable.
		public function solidify() : void
		{
			// Double the alpha value of each pixel
			for ( var i:int = 0; i < super.width; i++ )
			{
				for ( var j:int = 0; j < super.height; j++ )
				{
					var curColor:uint = super.pixels.getPixel32(i, j);
					var alpha:uint = curColor & 0xFF000000;
					alpha = alpha >> 24;
					alpha = alpha & 0x000000FF;
					alpha *= 3;
					if ( alpha > 255 )
						alpha = 255;
					
					alpha = alpha << 24;
					alpha = alpha & 0xFF000000;
					curColor = curColor & 0x00FFFFFF;
					curColor |= alpha;
					
					super.pixels.setPixel32(i, j, curColor);
				}
			}
		}
		
		public function collideBall(ball:Ball) : void
		{
			// The normal vector at this point in the arc
			var diffX:Number = 0;
			var diffY:Number = 0;
			
			// The average point of collision.  Used to make sure ball stays above ink
			var ptX:Number = 0;
			var ptY:Number = 0;
			
			// We need to know how many points collide for averaging
			var numCollisions:int = 0;
			
			// We will treat balls as circles
			var ballRadius:Number = ball.getRadius();
			var ballCenter:FlxPoint = new FlxPoint( ball.x, ball.y );
			
			// preserve velocity
			var vel:FlxPoint = ball.velocity;
			
			for ( var i:int = 0; i < dots.length; i++ )
			{
				// Better than pixel perfect!
				if ( FlxU.getDistance(ballCenter, points[i]) <= ballRadius )
				{
					// If we collide, add the approximate tangent at the point of
					// collision to the average tangent
					if ( i == 0 )
					{
						diffX += points[i + 1].x - points[i].x;
						diffY += points[i + 1].y - points[i].y;
					}
					else if ( i == dots.length - 1 )
					{
						diffX += points[i].x - points[i - 1].x;
						diffY += points[i].y - points[i - 1].y;
					}
					else
					{
						diffX += points[i + 1].x - points[i - 1].x;
						diffY += points[i + 1].y - points[i - 1].y;
					}
					
					ptX += points[i].x;
					ptY += points[i].y;
					
					numCollisions++;
				}
			}
			
			// Calculate the average tangent
			diffX /= numCollisions;
			diffY /= numCollisions;
			
			ptX /= numCollisions;
			ptY /= numCollisions;
			
			// Tell the ball about the collision, sending it the normal vector
			// (perpendicular to the tangent vector)
			if ( numCollisions > 0 )
			{
				ball.inkBounce( -diffY, diffX, ptX, ptY);
			}
		}
	}
}